function [numDecodingErrors] = fm3tr_code(BER,numBlockMessage)
%
% [numDecodingErrors] = fm3tr_code(BER,numBlockMessage)
%
% FM3TR Data Mode
% Two stage RS Encoder and Decoder
%
% Here's how this script works: 
% Block Encoder -> Hop Encoder -> Hop Decoder -> Block Decoder
%
% Block coder is RS(105,72,7) => 1 Codeword = 105 symbols, each symbol
% consits of 7 bits. Each codeword contains 72 information symbols, and the
% rest is parity
%
% Hop coder is RS(16,14,5) => 1 Codeword = 16 symbols, each symbol
% consits of 5 bits. Each codeword contains 14 information symbols, and the
% rest is parity
%
% Each message block is the single input to the block coder. 
% Each block coder input is 72 symbols * 7bits = 504 bits = 63 bytes
% Each block coder output is 105 symbols * 7bits = 735 bits
% Each hop coder input is 14 symbols * 5bits = 70  bits  
% Each hop coder output is  16 symbols * 5bits = 80bits = 10 bytes
% 
% For every 2 block of information (504*2 = 1008 bits), block coder
% generates 735*2 = 1470bits of information. This chunked into 21
% information symbols of size 70 bits by the hop coder. The hop coder
% generates 21 coded symbols of total size 1680 bits. 
% 
% Tansu Demirbilek
% ademirbi@mc.com
% Mercury Computer Systems


%********************%
%% Initialization
%********************%

% Block coding parameters
nBlock = 105; NBlock = 127;
kBlock = 72;  KBlock = 94;
mBlock = 7;   bBlock = 1;
% Primitive Polynomial: D^7+D^3+1 ==> p=137
pBlock = 137; 

% Hop coding parameters
nHop = 16; NHop = 31;
kHop = 14; KHop = 29;
mHop = 5;  bHop = 1;
% Primitive Polynomial: D^5+D^2+1 ==> p=37
pHop = 37;

numHopMessage = numBlockMessage*nBlock*mBlock/(kHop*mHop);

% Relationship between BER and BLER
BLER = 1-(1-BER).^nHop;

ErrorType = 'bler'; % ErrorType should be either 'num' or 'bler'

errorAmount = BLER; % errorAmount refers to number of errors per codeword 
                    % or BLER value depending on the value of errorType.

profileCode = 0;

%********************%
%% Profiling Init
%********************%
if (profileCode)
    profile clear;
    profile on -detail builtin -history;
end

%********************%
%% Block Encoding
%********************%


% generate static information message
infoMsg = [   17 125 68 91 98 101 102 85 98 8 77 119 73 108 46 49 73 ...
              5 84 42 48 4 114 92 104 113 76 47 87 65 81 117 56 62 28 ...
              44 126 54 8 93 52 8 5 46 33 94 65 104 119 46 11 52 90 41 ...
              70 43 63 97 36 42 98 44 89 11 31 10 5 55 107 66 63 19;
              17 125 68 91 98 101 102 85 98 8 77 119 73 108 46 49 73 ...
              5 84 42 48 4 114 92 104 113 76 47 87 65 81 117 56 62 28 ...
              44 126 54 8 93 52 8 5 46 33 94 65 104 119 46 11 52 90 41 ...
              70 43 63 97 36 42 98 44 89 11 31 10 5 55 107 66 63 19];

% generate random information message
%infoMsg = randint(numBlockMessage,kBlock,2^mBlock);

% Create the Galois array
msg = gf(infoMsg,mBlock); 

% Use kPlus1 since we padded an extra zero to the information symbols
blockEncodeOut = rs_encode(msg,nBlock,kBlock,bBlock);

%******************************%
%%  7 to 5 bit Conversion
%******************************%

conv7to5In = double(blockEncodeOut.x);

buffer = conv7to5In';

% Serialize the buffer (each 7bit codewords)
buffer = buffer(:);
buffer = buffer';

% Convert the buffer to binary
binBuffer = de2bi(buffer,mBlock,[],'left-msb');
binBuffer = binBuffer';
% Serialize the bits
binBuffer = binBuffer(:);
% Reformat the binary buffer
binBuffer = reshape(binBuffer,mHop,numBlockMessage*nBlock*mBlock/mHop);
binBuffer = binBuffer';
% Convert back to decimal
conv7to5out = bi2de(binBuffer,'left-msb');
conv7to5out = reshape(conv7to5out,kHop, numHopMessage);
conv7to5out = conv7to5out';


%********************%
%%  Hop Encoding
%********************%

hopEncodeIn = conv7to5out;

hopEncodeIn = gf(hopEncodeIn, mHop);

hopEncodeOut = rs_encode(hopEncodeIn,nHop,kHop,bHop); 


%********************%
%%  Introduce Errors
%  Errors are only introduced in this stage since the physical medium is
%  here
%********************%

[hopEncodeOut E]= rs_errors(hopEncodeOut,errorAmount,ErrorType);


%********************%
%%  Hop Decoding
%********************%

hopDecodeIn = hopEncodeOut;

[hopDecodeOut hopDecodeFailures] = rs_decode(hopDecodeIn, nHop, kHop, bHop);


%******************************%
%%  5 to 7 bit Conversion
%******************************%
conv5to7In = hopDecodeOut(:,1:kHop); % Do not include the redundant symbols
conv5to7In = double(conv5to7In.x);
buffer = conv5to7In';

% Serialize the buffer (each 7bit codewords)
buffer = buffer(:);
buffer = buffer';

% Convert the buffer to binary
binBuffer = de2bi(buffer,mHop,[],'left-msb');
binBuffer = binBuffer';
% Serialize the bits
binBuffer = binBuffer(:);
% Reformat the binary buffer
binBuffer = reshape(binBuffer,mBlock,numHopMessage*kHop*mHop/mBlock);
binBuffer = binBuffer';
% Convert back to decimal
conv5to7out = bi2de(binBuffer,'left-msb');
conv5to7out = reshape(conv5to7out,nBlock, numBlockMessage);
conv5to7out = conv5to7out';


%********************%
%% Block Decoding
%********************%

blockDecodeIn = conv5to7out;
blockDecodeIn = gf(blockDecodeIn,mBlock);

[decodedMsg blockDecodeFailures] = rs_decode(blockDecodeIn, nBlock, kBlock,bBlock);

% Extract the decoded message
decodedMsg = double(decodedMsg.x);
decodedMsg = decodedMsg(:,1:kBlock);

%********************%
%%      Result
%********************%
DecodeCheck = (sum((msg-decodedMsg)==0,2)==kBlock);
numDecodingErrors = numBlockMessage - sum(DecodeCheck);

result = isequal(infoMsg, decodedMsg);
% if result == 1, decoding was successful (unsuccessful otherwise)


%********************%
%% Profiling Init
%********************%
if(profileCode) profile report; end;

